// ListCtrlIpAccessStatesEdit.cpp : implementation file
//

#include "stdafx.h"
#include "ListCtrlIpAccessStatesEdit.h"

#include "eDASexpressApp.h"

extern CEDASexpressApp theApp;

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CListCtrlIpAccessStatesEdit

CListCtrlIpAccessStatesEdit::CListCtrlIpAccessStatesEdit()
{	
}

CListCtrlIpAccessStatesEdit::~CListCtrlIpAccessStatesEdit()
{
}


BEGIN_MESSAGE_MAP(CListCtrlIpAccessStatesEdit, CListCtrlIpAccessStatesShow)
	//{{AFX_MSG_MAP(CListCtrlIpAccessStatesEdit)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CListCtrlIpAccessStatesEdit message handlers

void CListCtrlIpAccessStatesEdit::PreSubclassWindow() 
{
	m_mapBackupGroups = m_mapIpAccessStatesGroups;
	
	CListCtrlIpAccessStatesShow::PreSubclassWindow();
}

// suspend : delete
// void CListCtrlIpAccessStatesEdit::ShowData()
// {
// // Column of gateway name
// // Compute the width of each state column
// 	const int iRolesCnt= m_arrRoles.GetSize();
// 	CRect rect;
// 		GetWindowRect( &rect );
// 	const int iEachStateColWidth= (rect.Width()-(iGatewayColWidth+1)-(1*iRolesCnt+1)) / iRolesCnt;
// 	const int iMINSTATECOLWIDTH= 75;
// 	const int iStateColWidth= iEachStateColWidth > iMINSTATECOLWIDTH ? iEachStateColWidth : iMINSTATECOLWIDTH;
// // Show gateways state of roles
// 	for (int iRoleIndex= 0; iRoleIndex < iRolesCnt; iRoleIndex++)
// 	{
// 		CRole & role= m_arrRoles[iRoleIndex];
// 		if (FALSE == GetColumn( iRoleIndex, NULL ))
// 			InsertColumn( iRoleIndex, role.m_strRoleName, LVCFMT_CENTER, iStateColWidth );
// 		POSITION pos;	int iItem;
// 		for (iItem=0,pos=role.m_mapGatewaysState.GetStartPosition(); pos; iItem++)
// 		{
// 			CString strRadiusIP;
// 			CRole::EIpAccessState eIpAccessState;
// 			role.m_mapGatewaysState.GetNextAssoc( pos, strRadiusIP, eIpAccessState );
// 
// 			LVITEM lvitem;
// 			lvitem.iItem = m_mapGatewaysIndex[strRadiusIP];
// 			lvitem.iSubItem = iRoleIndex;
// 			lvitem.mask = LVIF_IMAGE |LVIF_TEXT;
// 			lvitem.iImage = m_mapGatewayStateToImageindex[eIpAccessState];
// 			lvitem.pszText = (LPTSTR)(LPCTSTR)m_mapGatewayStateToName[eIpAccessState];
// 			VERIFY(TRUE == SetItem( &lvitem ));
// 		}
// 	}
// 
// 	int iItem;
// 	for (iItem= 0,posIP= m_mapGatewaysIndex.GetStartPosition(); posIP; iItem++)
// 	{
// 		CString strRadiusIP;	int iIndex;
// 		m_mapGatewaysIndex.GetNextAssoc( posIP, strRadiusIP, iIndex );
// 		SetItemText( iItem, iRolesCnt, strRadiusIP );
// 	}
// 
// // Drag the column of gateways name to first position
// 	CHeaderCtrl *pHeaderCtrl= GetHeaderCtrl();
// 	int iHeaderCtrlCount= pHeaderCtrl->GetItemCount();
// 	LPINT pnOrder= (LPINT) malloc(iHeaderCtrlCount*sizeof(int));
// 		ASSERT(pnOrder != NULL);
// 		pHeaderCtrl->GetOrderArray( pnOrder, iHeaderCtrlCount );
// 	int iTempOrder= pnOrder[iHeaderCtrlCount-1];
// 	for (int i= iHeaderCtrlCount-1; i > 0; i-- )
// 	{
// 		pnOrder[i] = pnOrder[i-1];
// 	}
// 	pnOrder[0] = iTempOrder;
// 	pHeaderCtrl->SetOrderArray(iHeaderCtrlCount, pnOrder);
// 	free(pnOrder);
// }

void CListCtrlIpAccessStatesEdit::OnLButtonDown(UINT nFlags, CPoint point) 
{
	HitState( point );

	CListCtrlData::OnLButtonUp(nFlags, point);
}

void CListCtrlIpAccessStatesEdit::OnLButtonUp(UINT nFlags, CPoint point) 
{
	if (!(MK_RBUTTON & nFlags))
		HitState( point );

	CListCtrlData::OnLButtonUp(nFlags, point);
}

void CListCtrlIpAccessStatesEdit::HitState(CPoint &point)
{
		UINT uFlags= 0;
	int iItem= HitTest( point, &uFlags );
	if (LVHT_NOWHERE == uFlags)
		return;

	int iSubItem= -1;
		CHeaderCtrl *pHeadCtrl= GetHeaderCtrl();
ASSERT(NULL != pHeadCtrl);
		const int iColsCount= pHeadCtrl->GetItemCount();
			for (int iTestSubItem= 0; iTestSubItem < iColsCount; iTestSubItem++)
			{
				CRect rectSubItemHead;
					pHeadCtrl->GetItemRect( iTestSubItem, rectSubItemHead );
				if ((rectSubItemHead.left < point.x) && (point.x < rectSubItemHead.right))
				{
					iSubItem = iTestSubItem;
					break;
				}
			}

	if ((iItem != -1)
	 && ((iSubItem != -1) && (iSubItem != m_iRadiusIpColIndex)))
	{
		ChangeState( iItem, iSubItem );
VERIFY(	RedrawItems( iItem, iItem )	== TRUE);
	}
}

void CListCtrlIpAccessStatesEdit::ChangeState(int iItem, int iSubItem)
{
	const CString &strGroupName= m_mapColumnSubItemToGroupName[iSubItem];
	const CString &strRadiusIP= m_mapItemToRadiusIP[iItem];
	EIpAccessState &state=  m_mapIpAccessStatesGroups[strGroupName][strRadiusIP];
	state = (state == ADMITTANCE) ? NO_ADMITTANCE : ADMITTANCE;	// Changing.
	if (state == m_mapBackupGroups[strGroupName][strRadiusIP])	// Judge change state.
	{
		if (0 == m_mapNewGroupNameToOriginal.GetCount())	// No renamed
		{
			BOOL ifAnyGroupChangeStates= FALSE;
				const int &iColCnt= GetHeaderCtrl()->GetItemCount();
				for (int iCol= 0; iCol < iColCnt; iCol++)
				{
					const CString &strGroupName= m_mapColumnSubItemToGroupName[iCol];
					if (TRUE == IsGroupChanged( strGroupName ))
					{
						ifAnyGroupChangeStates = TRUE;
						break;
					}
				}
			if (FALSE == ifAnyGroupChangeStates)
				::SendMessage( GetParent()->GetSafeHwnd(), WM_STATES_CHANGED, (WPARAM)SC_RENEW, 0 );
		}
	}
	else
	{
		::SendMessage( GetParent()->GetSafeHwnd(), WM_STATES_CHANGED, (WPARAM)SC_DIFFERENT, 0 );
	}

	SetState( iItem, iSubItem );
}

BOOL CListCtrlIpAccessStatesEdit::RenameGroup(const CString &strOriginalName, const CString &strNewName)
{
	CCopyableMap<CString,LPCTSTR,EIpAccessState,EIpAccessState> mapBackupIPsAccessState;
	if (FALSE == m_mapIpAccessStatesGroups.Lookup( strOriginalName, mapBackupIPsAccessState ))	// It isn't exist strOriginalName
		return FALSE;

	LVCOLUMN *plvc= &(m_itemdata.m_arrCols[m_mapGroupNameToSubItem[strOriginalName]]);
ASSERT(NULL != plvc);
		if (plvc->pszText != strOriginalName)
		{
			for (int iCol= 0; iCol < m_itemdata.m_arrCols.GetSize(); iCol++)
			{
				if (m_itemdata.m_arrCols[iCol].pszText == strOriginalName)
				{
					plvc = &(m_itemdata.m_arrCols[iCol]);
					break;
				}
			}
		}
ASSERT(NULL != plvc);
	plvc->pszText = (LPTSTR)(LPCTSTR)strNewName;
	LVCOLUMN lvc(*plvc);
		lvc.mask = LVCF_TEXT;
	SetColumn( lvc.iSubItem, &lvc );

ASSERT(TRUE==
	m_mapIpAccessStatesGroups.RemoveKey( strOriginalName )	);
	m_mapIpAccessStatesGroups.SetAt( strNewName, mapBackupIPsAccessState );

	int iOriginalSubItem= m_mapGroupNameToSubItem[strOriginalName];
	m_mapColumnSubItemToGroupName[iOriginalSubItem] = strNewName;
ASSERT(TRUE==
	m_mapGroupNameToSubItem.RemoveKey( strOriginalName )	);
	m_mapGroupNameToSubItem.SetAt( strNewName, iOriginalSubItem );

	CString strOriginalOld;
	if (TRUE == m_mapNewGroupNameToOriginal.Lookup( strOriginalName, strOriginalOld ))
	{
ASSERT(TRUE==
		m_mapNewGroupNameToOriginal.RemoveKey( strOriginalName )	);
		if (strNewName != strOriginalOld)	// Set new rename relation.
		{
			m_mapNewGroupNameToOriginal[strNewName] = strOriginalOld;
		// Must send changed message before,therefor no need
		}
		else
		{
			if (m_mapNewGroupNameToOriginal.GetCount() > 0)
			{
			// Must send changed message before,therefor no need
			}
			else
			{
				if (TRUE == IsGroupChanged( strNewName ))
					::SendMessage( GetParent()->GetSafeHwnd(), WM_STATES_CHANGED, (WPARAM)SC_DIFFERENT, 0 );
				else
					::SendMessage( GetParent()->GetSafeHwnd(), WM_STATES_CHANGED, (WPARAM)SC_RENEW, 0 );
			}
		}
	}
	else
	{
		m_mapNewGroupNameToOriginal[strNewName] = strOriginalName;
		::SendMessage( GetParent()->GetSafeHwnd(), WM_STATES_CHANGED, (WPARAM)SC_DIFFERENT, 0 );
	}

return (TRUE);
}

BOOL CListCtrlIpAccessStatesEdit::IsGroupChanged(const CString &strTestedGroupName)
{
	if (TRUE == m_mapNewGroupNameToOriginal.Lookup( strTestedGroupName, CString() ))
		return (FALSE);	// Renamed

	BOOL ifStateChanged= FALSE;	// Default is Neither renamed nor state changed
	CCopyableMap<CString,LPCTSTR,EIpAccessState,EIpAccessState> &mapIPsAccessStates= m_mapBackupGroups[strTestedGroupName];
	POSITION posIP= mapIPsAccessStates.GetStartPosition();
	while (posIP)
	{
		CString strRadiusIP;
		EIpAccessState eIpAccessState;
			mapIPsAccessStates.GetNextAssoc( posIP, strRadiusIP, eIpAccessState );
		if (eIpAccessState != m_mapIpAccessStatesGroups[strTestedGroupName][strRadiusIP])
		{
			ifStateChanged = TRUE;
			break;
		}
	}

	return (ifStateChanged);
}

// suspend : delete
// BOOL CListCtrlIpAccessStatesEdit::IsChanged()
// {
// 	if (m_mapIpAccessStatesGroups.GetCount() != m_mapBackupGroups.GetCount())	// As added or deleted
// 		return (FALSE);
// 	POSITION posBackupRole= m_mapBackupGroups.GetStartPosition();
// 	while (posBackupRole)
// 	{
// 		CString strBackupRoleName;
// 		CCopyableMap<CString,LPCTSTR,EIpAccessState,EIpAccessState> mapBackupIPsAccessState;
// 		m_mapBackupGroups.GetNextAssoc( posBackupRole, strBackupRoleName, mapBackupIPsAccessState );
// 
// 		CCopyableMap<CString,LPCTSTR,EIpAccessState,EIpAccessState> mapNewGatewaysState;
// 		if (FALSE == m_mapIpAccessStatesGroups.Lookup( strBackupRoleName, mapNewGatewaysState ))	// As rename
// 		{
// #ifdef _DEBUG
// 			BOOL ifRename= FALSE;
// 			POSITION posNewName= m_mapNewGroupNameToOriginal.GetStartPosition();
// 			while (posNewName)
// 			{
// 				CString strNewName;
// 				CString strOriginalName;
// 				m_mapNewGroupNameToOriginal.GetNextAssoc( posNewName, strNewName, strOriginalName );
// 
// 				if (strOriginalName == strBackupRoleName)
// 				{
// 					ifRename = TRUE;
// 					break;
// 				}
// 			}
// ASSERT(TRUE == ifRename);
// #endif
// 			return (FALSE);
// 		}
// 
// 		POSITION posBackupGateway= mapBackupIPsAccessState.GetStartPosition();
// 		while (posBackupGateway)
// 		{
// 			CString strBackupGatewayName;
// 			EIpAccessState eBackupGatewayState;
// 			mapBackupIPsAccessState.GetNextAssoc( posBackupGateway, strBackupGatewayName, eBackupGatewayState );
// 
// 			EIpAccessState eNewGatewayState;
// 			if (FALSE == mapNewGatewaysState.Lookup( strBackupGatewayName, eNewGatewayState ))	// As state changed
// 				return (FALSE);
// 		}
// 	}
// 	return (TRUE);
// }

void CListCtrlIpAccessStatesEdit::GetChangedGroups(CCopyableMap<CString,LPCTSTR,CStringItemsArray,CStringItemsArray&> &mapStatesGroups)
{
	mapStatesGroups.RemoveAll();

	POSITION posGroup= m_mapIpAccessStatesGroups.GetStartPosition();
	while (posGroup)
	{
		CString strGroupName;
		CCopyableMap<CString,LPCTSTR,EIpAccessState,EIpAccessState> mapIPsAccessState;
			m_mapIpAccessStatesGroups.GetNextAssoc( posGroup, strGroupName, mapIPsAccessState );
		if ((TRUE == m_mapNewGroupNameToOriginal.Lookup( strGroupName, CString() ))
		 || (TRUE == IsGroupChanged( strGroupName )))
		{
			CStringItemsArray arrNewAdmittances;
				POSITION posIP= mapIPsAccessState.GetStartPosition();
				while (posIP)
				{
					CString strRadiusIP;
					EIpAccessState eState;
						mapIPsAccessState.GetNextAssoc( posIP, strRadiusIP, eState );
					if (ADMITTANCE == eState)
						arrNewAdmittances.Add( strRadiusIP );
				}
			mapStatesGroups.SetAt( strGroupName, arrNewAdmittances );
		}
	}
}

void CListCtrlIpAccessStatesEdit::Reset()
{
// Reset group name back
	POSITION posName= m_mapNewGroupNameToOriginal.GetStartPosition();
	while (posName)
	{
		CString strNewName;
		CString strOriginal;
		m_mapNewGroupNameToOriginal.GetNextAssoc( posName, strNewName, strOriginal );
ASSERT(	RenameGroup( strNewName, strOriginal )	== TRUE );
	}
// Reset difference
	for (int iItem= 0; iItem < GetItemCount(); iItem++)
	{
			const CString &strRadiusIP= m_mapItemToRadiusIP[iItem];
		for (int iSubItem= 0; iSubItem < m_mapIpAccessStatesGroups.GetCount(); iSubItem++)
		{
			CString &strGroupName= m_mapColumnSubItemToGroupName[iSubItem];
			EIpAccessState &eBackupState= m_mapBackupGroups[strGroupName][strRadiusIP];
			EIpAccessState &eCurrentState= m_mapIpAccessStatesGroups[strGroupName][strRadiusIP];
			if (eCurrentState != eBackupState)
			{
				ChangeState( iItem, iSubItem );	// Change back
			}
		}
	}
}
